﻿using System;
using System.Threading;

namespace Chapter1.Recipe9
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Incorrect counter");

            var c = new Counter();

            var t1 = new Thread(() => TestCounter(c));
            var t2 = new Thread(() => TestCounter(c));
            var t3 = new Thread(() => TestCounter(c));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();

            Console.WriteLine("Total count: {0}", c.Count);
            Console.WriteLine("--------------------------");

            Console.WriteLine("Correct counter");

            var c1 = new CounterWithLock();

            t1 = new Thread(() => TestCounter(c1));
            t2 = new Thread(() => TestCounter(c1));
            t3 = new Thread(() => TestCounter(c1));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine("Total count: {0}", c1.Count);
            Console.ReadKey();

        }

        static void TestCounter(CounterBase c)
        {
            Console.WriteLine("线程ID：" + Thread.CurrentThread.ManagedThreadId);
            for (int i = 0; i < 5; i++)
            {
                c.Increment();
                c.Decrement();
            }
        }

        class Counter : CounterBase
        {
            public int Count { get; private set; }

            public override void Increment()
            {
                Count++;
                Console.WriteLine("++ Count={0} 线程ID={1}", Count, Thread.CurrentThread.ManagedThreadId);
            }

            public override void Decrement()
            {
                Count--;
                Console.WriteLine("-- Count={0} 线程ID={1}", Count, Thread.CurrentThread.ManagedThreadId);
            }
        }

        class CounterWithLock : CounterBase
        {
            private readonly object _syncRoot = new Object();
            public int Count { get; private set; }
            public override void Increment()
            {
                lock (_syncRoot)
                {
                    Count++;
                    Console.WriteLine("++ Count={0} 线程ID={1}", Count, Thread.CurrentThread.ManagedThreadId);
                }
            }

            public override void Decrement()
            {
                lock (_syncRoot)
                {
                    Count--;
                    Console.WriteLine("-- Count={0} 线程ID={1}", Count, Thread.CurrentThread.ManagedThreadId);
                }
            }
        }

        abstract class CounterBase
        {
            public abstract void Increment();
            public abstract void Decrement();
        }
    }
	
}


